Option Explicit

'################################################################
' Discriptor
' 一维数据对象的切片引用
' 索引式切片引用
' 需要提供一个 INT 型的 Series 作为切片的索引
'
' 当前对象相当于将索引Series + 数据Series 绑定在了一起
' 如果在外部主动修改了索引Series 将会直接影响当前索引对象的内容!!!!!
'
' 如果直接在当前对象外侧向索引对象中添加超出数据对象行数的索引，
' 将不会产生任何检查，当前通过这个异常索引获取数据时将会产生异常
'
' 空引用
'   当前切片可以产生一种特殊的引用: 空引用
'   空引用的索引使用: DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL 表示
'   访问空引用对应的数据时，将会返回一个 Empty
'   如果要设置空引用的数据，默认将不会执行任何操作
'   执行数据计算操作时，将会自动忽略空引用数据
'   对于空引用数据，将不会产生数据描述器
'   对于空引用数据，将不会进行数据填充
'################################################################


Implements IDFSeries

'################################################################
' Field
'################################################################
' 被代理的数据对象
Private delegatedSeries As IDFSeries

' 索引数据
Private indexSeries As IDFSeries

'################################################################
' Constructor
'################################################################
Private Sub Class_Initialize()
End Sub

Private Sub Class_Terminate()
End Sub

'################################################################
' Init
'################################################################
' 初始化
'
' @param data 数据对象
' @param indexes 索引对象
Public Sub Init(ByRef data As IDFSeries, ByRef indexes As IDFSeries)
    ' 1. 检查参数
    If data Is Nothing Then
        Err.Raise 10001, Description:="parameter data must be not nothing"
        Exit Sub
    End If
    If indexes Is Nothing Then
        Err.Raise 10001, Description:="parameter indexes must be not nothing"
        Exit Sub
    End If

    ' indexes 必须是 INT 型
    If indexes.DataType <> DF_DataType.DF_INT Then
        Err.Raise 10111, Description:="parameter indexes's data type must be DF_DataType.DF_INT"
        Exit Sub
    End If

    ' 2. 保存数据
    Set delegatedSeries = data
    Set indexSeries = indexes
End Sub

'################################################################
' Property
'################################################################
' 获取当前一维数据对象中的数据类型
Public Property Get IDFSeries_DataType() As DF_DataType
    IDFSeries_DataType = delegatedSeries.DataType
End Property

' 获取当前一维数据对象中的数据数量
Public Property Get IDFSeries_Size() As Long
    IDFSeries_Size = indexSeries.Size
End Property

' 返回当前数据对象所使用的数据类型处理器
Public Property Get IDFSeries_TypeHandler() As IDFDataTypeHandler
    Set IDFSeries_TypeHandler = delegatedSeries.TypeHandler
End Property

'################################################################
' unsafe Function
' 内置方法/加速方法，为了防止异常，在外部如果没有完善的检测机制不应该主动调用
'################################################################
' 内置取值方法
' 将不会对索引范围进行检查
Public Function IDFSeries_unsafeGetData(ByRef index As Long) As Variant
    ' 1. 从索引对象中获取真实索引
    Dim i As Variant
    i = indexSeries.unsafeGetData(index)

    ' 2. 如果是空引用，则需要返回 Empty
    If i = DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
        IDFSeries_unsafeGetData = Empty
        Exit Function
    End If

    ' 3. 通过真实索引获取数据
    IDFSeries_unsafeGetData = delegatedSeries.unsafeGetData(i)
End Function

' 内置设置方法
' 将不会对索引范围进行检查
' 将不会对数据进行标准化处理
Public Sub IDFSeries_unsafeSetData(ByRef index As Long, ByRef val As Variant)
    ' 1. 从索引对象中获取真实索引
    Dim i As Variant
    i = indexSeries.unsafeGetData(index)

    ' 2. 如果是空引用，则立刻结束
    If i = DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
        Exit Sub
    End If

    ' 3. 通过真实索引写入数据
    delegatedSeries.unsafeSetData i, val
End Sub

'################################################################
' Function
'################################################################
'--------------------------------------------------
' 手动添加索引引用
'--------------------------------------------------
' 向末尾添加一个原始 Series 的索引引用
'
' @param originIndex 原始 Series 的索引
Public Sub appendRef(ByRef originIndex As Long)
    ' 1. 检查索引是否存在，如果不存在需要抛出异常
    If originIndex < 0 Then
        Err.Raise 10110, Description:="parameter originIndex=" & originIndex & " out of bounds. delegatedSeries's min index=0, max index[" & (delegatedSeries.Size - 1) & "]"
        Exit Function
    ElseIf originIndex >= delegatedSeries.Size Then
        Err.Raise 10110, Description:="parameter originIndex=" & originIndex & " out of bounds. delegatedSeries's min index=0, max index[" & (delegatedSeries.Size - 1) & "]"
        Exit Function
    End If

    ' 2. 将引用的索引写入索引对象
    indexSeries.appendData originIndex
End Sub

' 向末尾添加一个空引用
'
Public Sub appendEmptyRef()
    indexSeries.appendData DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL
End Sub

'--------------------------------------------------
' 缓存回收
'--------------------------------------------------
Public Sub IDFSeries_cacheCollect()
    ' 数据对象 + 索引对象分别进行缓存回收
    delegatedSeries.cacheCollect
    indexSeries.cacheCollect
End Sub

'--------------------------------------------------
' 数据读写
'--------------------------------------------------

' 检查索引是否在安全范围内
' 这里只检查索引对象
Public Function IDFSeries_hasIndex(ByRef index As Long) As Boolean
    If index < 0 Then
        IDFSeries_hasIndex = False
        Exit Function
    End If

    If index >= indexSeries.Size Then
        IDFSeries_hasIndex = False
        Exit Function
    End If

    IDFSeries_hasIndex = True
End Function

' 获取指定索引位置的数据
'
' @param index 数据索引
' @return 指定索引位置上的数据
Public Function IDFSeries_getData(ByRef index As Long) As Variant
On Error Goto catch1:
    ' 1. 获取真实索引
    Dim i As Variant
    i = indexSeries.getData(index)
    Goto getRealData
catch1:
    Err.Raise Err.Number, Description:=Err.Description
    Exit Function

getRealData:

    ' 2. 如果是空引用，则需要返回 Empty
    If i = DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
        IDFSeries_getData = Empty
        Exit Function
    End If

    ' 3. 获取真实数据
On Error Goto catch2:
    ' 从代理中获取真实数据
    IDFSeries_getData = delegatedSeries.getData(Int(i))
    Exit Function
catch2:
    ' 处理索引范围异常，其他异常正常抛出
    Err.Raise Err.Number, Description:=Err.Description
End Function

' 设置指定索引位置的数据
'
' @param index 数据索引
' @param val 需要设置的数据
Public Sub IDFSeries_setData(ByRef index As Long, ByRef val As Variant)
On Error Goto catch1:
    ' 1. 获取真实索引
    Dim i As Variant
    i = indexSeries.getData(index)
    Goto setRealData
catch1:
    Err.Raise Err.Number, Description:=Err.Description
    Exit Sub

setRealData:

    ' 2. 如果是空引用，则需要返回 Empty
    If i = DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
        Exit Sub
    End If

On Error Goto catch2:
    delegatedSeries.setData i, val
    Exit Sub
catch2:
    ' 处理索引范围异常，其他异常正常抛出
    Err.Raise Err.Number, Description:=Err.Description
End Sub

'--------------------------------------------------
' CRUD
'--------------------------------------------------

' 向末尾新增一个数据
'
' @param val 需要设置的数据
Public Sub IDFSeries_appendData(ByRef val As Variant)
    ' 1. 向数据对象的末尾添加数据
    delegatedSeries.appendData val

    ' 2. 添加索引
    indexSeries.appendData (delegatedSeries.Size - 1)
End Sub

' 向末尾新增一个或多个空数据
'
' @param count 需要添加的空数据的数量，默认=1
Public Sub IDFSeries_appendEmpty(Optional ByRef count As Long = 1)
    ' 1. 保存添加前的数据索引
    Dim dataMaxIdxBeforeAdd As Long
    dataMaxIdxBeforeAdd = delegatedSeries.Size - 1

    ' 2. 向数据对象中添加空行
    delegatedSeries.appendEmpty count

    ' 3. 添加索引
    Dim i As Long
    For i = dataMaxIdxBeforeAdd To delegatedSeries.Size - 1
        indexSeries.appendData i
    Next
End Sub

' 删除指定索引位置的数据。只删除当前对象内的数据
' 该方法会导致内部数据产生移动，如果数据量很大，将会花费大量时间
'
' @param index 数据索引
Public Sub IDFSeries_delData(ParamArray indexes() As Variant)
    Dim ies As Variant
    ies = indexes
    IDFSeries_delDataByIndexArray ies
End Sub

' 删除指定索引位置的数据。只删除当前对象内的数据
' 该方法会导致内部数据产生移动，如果数据量很大，将会花费大量时间
'
' @param index 数据索引
Public Sub IDFSeries_delDataByIndexArray(ByRef indexes As Variant)
    ' 只删除索引
    indexSeries.delDataByIndexArray indexes
End Sub

' 删除指定索引位置的数据。如果当前是引用对象，也会直接删除原始对象中的数据
' 该方法会导致内部数据产生移动，如果数据量很大，将会花费大量时间
'
' @param index 数据索引
Public Sub IDFSeries_deepDelData(ParamArray indexes() As Variant)
    Dim ies As Variant
    ies = indexes
    IDFSeries_deepDelDataByIndexArray ies
End Sub

' 删除指定索引位置的数据。如果当前是引用对象，也会直接删除原始对象中的数据
' 该方法会导致内部数据产生移动，如果数据量很大，将会花费大量时间
'
' @param index 数据索引
Public Sub IDFSeries_deepDelDataByIndexArray(ByRef indexes As Variant)
    ' 1. 如果没有有效参数，则立刻停止
    Dim idxMax As Long
    Dim idxMin As Long
    Dim delSize As Long
    idxMin = LBound(indexes)
    idxMax = UBound(indexes)
    delSize = idxMax - idxMin + 1
    If delSize = 0 Then
        Exit Sub
    End If

    ' 2. 从参数中获取所有的真实索引（需要忽略空引用的索引）
    Dim realIndexes() As Long
    ReDim realIndexes(0 To (delSize - 1))
    Dim tempIdx As Long

    Dim i As Integer
    Dim realIndexesSize As Long
    realIndexesSize = 0
    For i = idxMin To idxMax
        tempIdx = indexSeries.getData(indexes(i))

        ' 如果不是空引用，则保存真实索引
        If tempIdx <> DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            realIndexes(realIndexesSize) = tempIdx
            realIndexesSize = realIndexesSize + 1
        End If
    Next

    ' 3. 检查收集到的真实索引的数量，如果数量不一致，说明存在空引用
    '    需要回收真实索引数组的部分空间
    If realIndexesSize < delSize Then
        ReDim Preserve realIndexes(0 To (realIndexesSize - 1))
    End If

    ' 4. 从数据对象中删除数据
    delegatedSeries.deepDelDataByIndexArray realIndexes

    ' 4. 从索引对象中删除索引
    indexSeries.deepDelDataByIndexArray indexes
End Sub

' 拷贝指定索引的数据到末尾
'
' @param index 数据索引
' @optional-param needDescriptor 如果数据存在描述符，是否需要拷贝，默认=False
Public Sub IDFSeries_copyAndAppend(ByRef index As Long, Optional ByRef needDescriptor As Boolean=False)
On Error Goto catch1:
    ' 1. 获取真实索引
    Dim i As Variant
    i = indexSeries.getData(index)
    Goto realCopy
catch1:
    Err.Raise Err.Number, Description:=Err.Description
    Exit Sub

realCopy:

    ' 2. 如果是空引用，则需要在末尾添加一个空引用
    If i = DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
        appendEmptyRef
        Exit Sub
    End If

On Error Goto catch2:
    ' 2. 执行被代理对象的数据拷贝
    delegatedSeries.copyAndAppend i, needDescriptor

    ' 3. 添加新数据行的引用
    appendRef (delegatedSeries.Size - 1)
catch2:
    Err.Raise Err.Number, Description:=Err.Description
End Sub

' 使用指定数据填充内部所有数据是 Empty 的槽位
'
' 如果参数 val 无法被标准化为与当前 IDFSeries 类型相同的数据，将不会进行数据填充
'
' 对于切片类型，应该只填充引用的那些槽位，未引用的槽位不应该进行修改
'
' 对于空引用数据，将不会进行数据填充
'
' @param val 用来填充的数据
Public Sub IDFSeries_fillEmptySlot(ByRef val As Variant)
    ' 1. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 2. 标准化填充数据
    Dim fillVal As Variant
    fillVal = dataTypeHandler.normalize(val)

    ' 3. 如果标准化失败（参数 val 无法和当前 IDFSeries 的类型统一），则放弃填充操作
    If IsEmpty(fillVal) Then
        End Sub
    End If

    ' 3. 遍历整个对象，搜索引用中的 Empty 槽位，并填充数据
    Dim i As Long
    Dim realIndex As Variant
    For i = 0 To (IDFSeries_Size - 1)
        ' 3.1 获取真实索引
        realIndex = indexSeries.unsafeGetData(i)

        ' 3.2 自动忽略空引用行
        If realIndex = DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            Goto continue1
        End If

        ' 3.3 如果当前的引用是 Empty 槽位，则进行填充
        If IsEmpty(delegatedSeries.unsafeGetData(realIndex)) Then
            delegatedSeries.unsafeSetData realIndex, fillVal
        End If

continue1:
    Next
End Sub

'--------------------------------------------------
' 数据计算
'--------------------------------------------------
'===========
' 基础类型计算
'===========
' 对所有数据进行指定方式的运算
'
' @param funcStr 运算函数名字符串
'        需要提供形式为 Function method(ByRef origin As Variant) As Variant 的方法
Public Sub IDFSeries_exec(ByRef funcStr As String)
    ' 1. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 2. 获取各索引上的真实值，计算后再重新保存
    '    自动忽略空引用行
    Dim i As Long
    Dim realIndex As Variant
    For i = 0 To (IDFSeries_Size - 1)
        realIndex = indexSeries.unsafeGetData(i)
        If realIndex <> DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            delegatedSeries.unsafeSetData realIndex, dataTypeHandler.normalize(Application.Run(funcStr, delegatedSeries.unsafeGetData(realIndex)))
        End If
    Next
End Sub

' 对所有数据进行指定方式的运算
'
' @param v 运算数据
' @param funcStr 运算函数名字符串
'        需要提供形式为 Function method(ByRef origin As Variant, ByRef computeVal As Variant) As Variant 的方法
Public Sub IDFSeries_compute(ByRef v As Variant, ByRef funcStr As String)
    ' 1. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 2. 获取各索引上的真实值，计算后再重新保存
    '    自动忽略空引用行
    Dim i As Long
    Dim realIndex As Variant
    For i = 0 To (IDFSeries_Size - 1)
        realIndex = indexSeries.unsafeGetData(i)
        If realIndex <> DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            delegatedSeries.unsafeSetData realIndex, dataTypeHandler.normalize( _
                Application.Run(funcStr, delegatedSeries.unsafeGetData(realIndex), v) _
            )
        End If
    Next

End Sub

' 对所有数据进行加法运算
'
' 整型，做加法
' 浮点型，做加法
' 字符串，将会直接做字符串连接
' 日期，以天为单位做加法
' 时间，以秒为单位做加法
' 时间戳，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 布尔型，将不会做处理，如果有需要请使用 compute 或 exec 方法
'
' @param v 运算数据
Public Sub IDFSeries_add(ByRef v As Variant)
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 如果当前类型不支持该操作，则立刻停止
    If dataTypeHandler.SupportAdd = False Then
        Exit Sub
    End If

    ' 2. 将运算数据转换成标准计算类型数据
    Dim computeData As Variant
    computeData = dataTypeHandler.normalizeComputeData(v)

    ' 3. 如果计算数据是 Empty，则不做计算
    If IsEmpty(computeData) Then
        Exit Sub
    End If

    ' 4. 对所有数据进行计算
    '    自动忽略空引用行
    Dim i As Long
    Dim realIndex As Variant
    For i = 0 To (IDFSeries_Size - 1)
        realIndex = indexSeries.unsafeGetData(i)

        If realIndex <> DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            delegatedSeries.unsafeSetData _
                realIndex, _
                dataTypeHandler.add( _
                    delegatedSeries.unsafeGetData(realIndex), _
                    computeData _
                )
        End If
    Next
End Sub

' 对所有数据进行减法运算
'
' 整型，做减法
' 浮点型，做减法
' 字符串，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 日期，以天为单位做减法
' 时间，以秒为单位做减法
' 时间戳，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 布尔型，将不会做处理，如果有需要请使用 compute 或 exec 方法
'
' @param v 运算数据
Public Sub IDFSeries_subtract(ByRef v As Variant)
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 如果当前类型不支持该操作，则立刻停止
    If dataTypeHandler.SupportSubtract = False Then
        Exit Sub
    End If

    ' 2. 将运算数据转换成标准计算类型数据
    Dim computeData As Variant
    computeData = dataTypeHandler.normalizeComputeData(v)

    ' 3. 如果计算数据是 Empty，则不做计算
    If IsEmpty(computeData) Then
        Exit Sub
    End If

    ' 4. 对所有数据进行计算
    '    自动忽略空引用行
    Dim i As Long
    Dim realIndex As Variant
    For i = 0 To (IDFSeries_Size - 1)
        realIndex = indexSeries.unsafeGetData(i)

        If realIndex <> DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            delegatedSeries.unsafeSetData _
                realIndex, _
                dataTypeHandler.subtract( _
                    delegatedSeries.unsafeGetData(realIndex), _
                    computeData _
                )
        End If
    Next
End Sub

' 对所有数据进行乘法运算
'
' 整型，做乘法
' 浮点型，做乘法
' 字符串，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 日期，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 时间，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 时间戳，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 布尔型，将不会做处理，如果有需要请使用 compute 或 exec 方法
'
' @param v 运算数据
Public Sub IDFSeries_multiply(ByRef v As Variant)
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 如果当前类型不支持该操作，则立刻停止
    If dataTypeHandler.SupportMultiply = False Then
        Exit Sub
    End If

    ' 2. 将运算数据转换成标准计算类型数据
    Dim computeData As Variant
    computeData = dataTypeHandler.normalizeComputeData(v)

    ' 3. 如果计算数据是 Empty，则不做计算
    If IsEmpty(computeData) Then
        Exit Sub
    End If

    ' 4. 对所有数据进行计算
    '    自动忽略空引用行
    Dim i As Long
    Dim realIndex As Variant
    For i = 0 To (IDFSeries_Size - 1)
        realIndex = indexSeries.unsafeGetData(i)

        If realIndex <> DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            delegatedSeries.unsafeSetData _
                realIndex, _
                dataTypeHandler.multiply( _
                    delegatedSeries.unsafeGetData(realIndex), _
                    computeData _
                )
        End If
    Next
End Sub

' 对所有数据进行除法运算
'
' 整型，做除法
' 浮点型，做除法
' 字符串，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 日期，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 时间，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 时间戳，将不会做处理，如果有需要请使用 compute 或 exec 方法
' 布尔型，将不会做处理，如果有需要请使用 compute 或 exec 方法
'
' @param v 运算数据
Public Sub IDFSeries_divide(ByRef v As Variant)
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 如果当前类型不支持该操作，则立刻停止
    If dataTypeHandler.SupportDivide = False Then
        Exit Sub
    End If

    ' 2. 将运算数据转换成标准计算类型数据
    Dim computeData As Variant
    computeData = dataTypeHandler.normalizeComputeData(v)

    ' 3. 如果计算数据是 Empty，则不做计算
    If IsEmpty(computeData) Then
        Exit Sub
    End If

    ' 4. 对所有数据进行计算
    '    自动忽略空引用行
    Dim i As Long
    Dim realIndex As Variant
    For i = 0 To (IDFSeries_Size - 1)
        realIndex = indexSeries.unsafeGetData(i)

        If realIndex <> DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            delegatedSeries.unsafeSetData _
                realIndex, _
                dataTypeHandler.divide( _
                    delegatedSeries.unsafeGetData(realIndex), _
                    computeData _
                )
        End If
    Next
End Sub

'===========
' 和其他 Series 类型做计算
'===========
' 和其他 Series 做加法运算，计算结果合并到当前 Series
'
' @param desc 运算 Series
Public Sub IDFSeries_mergeAdd(ByRef desc As Series)
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    dataTypeHandler.mergeAdd Me, desc
End Sub

' 和其他 Series 做减法运算，计算结果合并到当前 Series
'
' @param desc 运算 Series
Public Sub IDFSeries_mergeSubtract(ByRef desc As Series)
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    dataTypeHandler.mergeSubtract Me, desc
End Sub

' 和其他 Series 做乘法运算，计算结果合并到当前 Series
'
' @param desc 运算 Series
Public Sub IDFSeries_mergeMultiply(ByRef desc As Series)
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    dataTypeHandler.mergeMultiply Me, desc
End Sub

' 和其他 Series 做除法运算，计算结果合并到当前 Series
'
' @param desc 运算 Series
Public Sub IDFSeries_mergeDivide(ByRef desc As Series)
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    dataTypeHandler.mergeDivide Me, desc
End Sub

'=============
' 生成 Boolean IDFSeries
'=============
' 和指定运算符进行比较，返回一个和当前 series 相同的 Boolean 型的 series
' =
Public Function IDFSeries_eq(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_eq = dataTypeHandler.eqForSeries(Me, v)
End Function

' !=
Public Function IDFSeries_ne(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_ne = dataTypeHandler.neForSeries(Me, v)
End Function

' >
Public Function IDFSeries_gt(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_gt = dataTypeHandler.gtForSeries(Me, v)
End Function

' <
Public Function IDFSeries_lt(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_lt = dataTypeHandler.ltForSeries(Me, v)
End Function

' >=
Public Function IDFSeries_ge(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_ge = dataTypeHandler.geForSeries(Me, v)
End Function

' <=
Public Function IDFSeries_le(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_le = dataTypeHandler.leForSeries(Me, v)
End Function

' In()
Public Function IDFSeries_inVals(ByRef vs As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_inVals = dataTypeHandler.inValsForSeries(Me, vs)
End Function

' between
Public Function IDFSeries_between(ByRef left As Variant, ByRef right As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_between = dataTypeHandler.betweenForSeries(Me, left, right)
End Function

'=============
' 生成 Series ，保存所有结果为 true 的数据
'=============
' =
Public Function IDFSeries_eqToSeries(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_eqToSeries = dataTypeHandler.eqToSeriesForSeries(Me, v)
End Function
' !=
Public Function IDFSeries_neToSeries(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_neToSeries = dataTypeHandler.neToSeriesForSeries(Me, v)
End Function
' >
Public Function IDFSeries_gtToSeries(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_gtToSeries = dataTypeHandler.gtToSeriesForSeries(Me, v)
End Function
' <
Public Function IDFSeries_ltToSeries(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_gtToSeries = dataTypeHandler.ltToSeriesForSeries(Me, v)
End Function
' >=
Public Function IDFSeries_geToSeries(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_geToSeries = dataTypeHandler.geToSeriesForSeries(Me, v)
End Function
' <=
Public Function IDFSeries_leToSeries(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_leToSeries = dataTypeHandler.leToSeriesForSeries(Me, v)
End Function
' In()
Public Function IDFSeries_inValsToSeries(ByRef vs As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_inValsToSeries = dataTypeHandler.inValsToSeriesForSeries(Me, vs)
End Function
' between
Public Function IDFSeries_betweenToSeries(ByRef left As Variant, ByRef right As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_betweenToSeries = dataTypeHandler.betweenToSeriesForSeries(Me, left, right)
End Function

'=============
' 生成 Series 切片，保存所有结果为 true 的数据的引用
'=============
' =
Public Function IDFSeries_eqToSlice(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_eqToSlice = dataTypeHandler.eqToSliceForSeries(Me, v)
End Function
' !=
Public Function IDFSeries_neToSlice(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_neToSlice = dataTypeHandler.neToSliceForSeries(Me, v)
End Function
' >
Public Function IDFSeries_gtToSlice(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_gtToSlice = dataTypeHandler.gtToSliceForSeries(Me, v)
End Function
' <
Public Function IDFSeries_ltToSlice(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_ltToSlice = dataTypeHandler.ltToSliceForSeries(Me, v)
End Function
' >=
Public Function IDFSeries_geToSlice(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_geToSlice = dataTypeHandler.geToSliceForSeries(Me, v)
End Function
' <=
Public Function IDFSeries_leToSlice(ByRef v As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_leToSlice = dataTypeHandler.leToSliceForSeries(Me, v)
End Function
' In()
Public Function IDFSeries_inValsToSlice(ByRef vs As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_inValsToSlice = dataTypeHandler.inValsToSliceForSeries(Me, vs)
End Function
' between
Public Function IDFSeries_betweenToSlice(ByRef left As Variant, ByRef right As Variant) As IDFSeries
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 执行计算
    Set IDFSeries_betweenToSlice = dataTypeHandler.betweenToSliceForSeries(Me, left, right)
End Function

'--------------------------------------------------
' 聚合运算
'--------------------------------------------------
' 返回 Series 中的最大值
'
' 如果 Series 中没有数据，则返回 Empty
' 如果当前 Series 的类型不支持 max 运算，则返回 Empty
'
Public Function IDFSeries_max() As Variant
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 如果当前类型不支持该操作，则立刻停止
    If dataTypeHandler.SupportMax = False Then
        Exit Function
    End If

    ' 2. 执行计算
    IDFSeries_max = dataTypeHandler.max(Me)
End Function

' 返回 Series 中的最小值
'
' 如果 Series 中没有数据，则返回 Empty
' 如果当前 Series 的类型不支持 min 运算，则返回 Empty
'
Public Function IDFSeries_min() As Variant
    ' 0. 获取类型处理器
    Dim dataTypeHandler As IDFDataTypeHandler
    Set dataTypeHandler = IDFSeries_TypeHandler

    ' 1. 如果当前类型不支持该操作，则立刻停止
    If dataTypeHandler.SupportMax = False Then
        Exit Function
    End If

    ' 2. 执行计算
    IDFSeries_max = dataTypeHandler.min(Me)
End Function

'--------------------------------------------------
' 数据描述符
'--------------------------------------------------

' 获取某个数据的描述器
' 如果不存在，则返回 Nothing
'
' @param index 数据索引
' @optional-param needCreate 如果描述信息对象不存在是否需要进行创建。默认值=False
' @return IDFDescriptor 数据描述器
Public Function IDFSeries_getDataDescriptor(ByRef index As Long, Optional ByRef needCreate As Boolean = False) As IDFDescriptor
On Error Goto catch1:
    ' 1. 获取真实索引
    Dim i As Variant
    i = indexSeries.getData(index)
    Goto realGetDataDescriptor
catch1:
    Err.Raise Err.Number, Description:=Err.Description
    Exit Function

realGetDataDescriptor:

    ' 2. 如果是空引用，默认不会产生描述器
    If i = DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
        Set IDFSeries_getDataDescriptor = Nothing
        Exit Function
    End If

    ' 3. 获取真实的数据描述器
    Set IDFSeries_getDataDescriptor = delegatedSeries.getDataDescriptor(Int(i), needCreate)
End Function

'--------------------------------------------------
' 切片操作
'--------------------------------------------------
' 切片
' @optional-param start Long 起始位置
' @optional-param stop Long 终止位置(最终不会包含 stop 的索引)
' @optional-param step Long 步长
Public Function IDFSeries_slice(Optional startIdx As Variant, Optional ByRef stopIdx As Variant, Optional ByRef step As Variant=1) As IDFSeries
    Dim result As DFSeriesSlice
    Set result = New DFSeriesSlice
    result.Init Me, startIdx, stopIdx, step

    Set IDFSeries_slice = result
End Function

' 使用指定索引创建切片
' @param-array indexes 需要的真实索引
Public Function IDFSeries_sliceByIndexes(ParamArray indexes() As Variant) As IDFSeries
    Dim ies As Variant
    ies = indexes

    Set IDFSeries_sliceByIndexes = IDFSeries_sliceByIndexArray(ies)
End Function

' 使用指定索引数组创建切片
' @param indexes 需要的真实索引
Public Function IDFSeries_sliceByIndexArray(ByRef indexes As Variant) As IDFSeries
    Dim result As DFSeriesSlice
    Set result = New DFSeriesSlice
    result.InitByIndexArray Me, indexes

    Set IDFSeries_sliceByIndexArray = result
End Function

'--------------------------------------------------
' 输出操作
'--------------------------------------------------

' 将 Series 中的内容输出到控制台
' 每个数据输出为一行
' Empty 将会以字符串 "@@EMPTY@@" 的形式输出
'
' @optional-param startIdx 输出的起始行(包括这一行，从 0 开始)
'                          只支持 0、正数，如果输入了一个负数，则自动使用 0
'                          如果 startIdx > endIdx，则不输出任何数据
' @optional-param endIdx 输出的结束行(包括这一行，从 0 开始)
'                          只支持 0、正数，如果输入了一个负数，则自动使用最大行索引
Public Sub IDFSeries_printToConsole(Optional ByRef startIdx As Long = 0, _
    Optional ByRef endIdx As Long = -1)

    ' 1. 如果当前 DF 没有任何行，则立刻结束
    Dim dataSize As Long
    dataSize = indexSeries.Size
    If dataSize = 0 Then
        Exit Sub
    End If

    ' 2. 确认参数
    Dim realStartIdx As Long
    Dim realEndIdx As Long
    If startIdx < 0 Then
        realStartIdx = 0
    Else
        If startIdx >= dataSize Then
            realStartIdx = dataSize - 1
        Else
            realStartIdx = startIdx
        End If
    End If
    If endIdx < 0 Then
        realEndIdx = dataSize - 1
    Else
        If endIdx >= dataSize Then
            realEndIdx = dataSize - 1
        Else
            realEndIdx = endIdx
        End If
    End If

    ' 如果 startIdx > endIdx，则不输出任何数据
    If realStartIdx > realEndIdx Then
        Exit Sub
    End If

    ' 3. 按行输出内容
    Dim i As Long
    Dim realDataIndex As Variant
    Dim temp As Variant
    For i = realStartIdx To realEndIdx
        realDataIndex = indexSeries.unsafeGetData(i)

        ' 2. 如果是空引用，则需要返回 Empty
        If i = DFHelper.SERIES_SLICE_EMPTY_REF_SLOT_VAL Then
            Debug.Print DFHelper.EMPTY_STR_IN_CONSOLE
        Else
            temp = delegatedSeries.unsafeGetData(realDataIndex)
            If IsEmpty(temp) Then
                Debug.Print DFHelper.EMPTY_STR_IN_CONSOLE
            Else
                Debug.Print temp & ""
            End If
        End If
    Next
End Sub